# ~*~ coding: utf-8 ~*~
import datetime
import traceback

from django.db import transaction
from django.utils import timezone
from django.db.utils import OperationalError

from common.utils import get_logger
from .base import CommandBase

logger = get_logger(__file__)
class CommandStore(CommandBase):

  def __init__(self, params):
    from terminal.models import Command
    self.model = Command

  def save(self, command):
    """
    保存命令到数据库
    """
    self.model.objects.create(
      user=command["user"], asset=command["asset"],
      system_user=command["system_user"], input=command["input"],
      output=command["output"], session=command["session"],
      risk_level=command.get("risk_level", 0), org_id=command["org_id"],
      timestamp=command["timestamp"]
    )

  def bulk_save(self, commands):
    """
    批量保存命令到数据库, command的顺序和save中一致
    """
    _commands = []
    for c in commands:
      logger.info("有高危指令啦" + str(c))
      _commands.append(self.model(
        user=c["user"], asset=c["asset"], system_user=c["system_user"],
        input=c["input"], output=c["output"], session=c["session"],
        risk_level=c.get("risk_level", 0), org_id=c["org_id"],
        timestamp=c["timestamp"],
        remote_address=c["remote_address"],
        manage_type=c["manage_type"],
        event_msg=c["event_msg"],
        asset_operating_system_type=c["asset_operating_system_type"],
        asset_registered_name=c["asset"],
        # asset_registered_name=c["asset_registered_name"],
      ))
    error = False
    try:
      with transaction.atomic():
        self.model.objects.bulk_create(_commands)
    except OperationalError:
      traceback.print_exc()
      error = True
    except:
      traceback.print_exc()
      return False

    if not error:
      return True
    for command in _commands:
      try:
        with transaction.atomic():
          command.save()
      except OperationalError:
        command.output = str(command.output.encode())
        command.save()
        traceback.print_exc()
    return True

  @staticmethod
  def make_filter_kwargs(
    date_from=None, date_to=None,
    user=None, asset=None, system_user=None,
    input=None, session=None, risk_level=None, org_id=None, is_read=None):
    filter_kwargs = {}
    date_from_default = timezone.now() - datetime.timedelta(days=17)
    date_to_default = timezone.now()

    if not date_from and not session:
      date_from = date_from_default
    if not date_to and not session:
      date_to = date_to_default
    if date_from is not None:
      if isinstance(date_from, datetime.datetime):
        date_from = date_from.timestamp()
      filter_kwargs['timestamp__gte'] = int(date_from)
    if date_to is not None:
      if isinstance(date_to, datetime.datetime):
        date_to = date_to.timestamp()
      filter_kwargs['timestamp__lte'] = int(date_to)

    if user:
      filter_kwargs["user__startswith"] = user
    if asset:
      filter_kwargs['asset'] = asset
    if system_user:
      filter_kwargs['system_user'] = system_user
    if input:
      filter_kwargs['input__icontains'] = input
    if session:
      filter_kwargs['session'] = session
    if org_id is not None:
      filter_kwargs['org_id'] = org_id
    if risk_level is not None:
      filter_kwargs['risk_level'] = risk_level
    if is_read is not None:
      filter_kwargs['is_read'] = is_read
    return filter_kwargs

  def filter(self, date_from=None, date_to=None,
             user=None, asset=None, system_user=None,
             input=None, session=None, risk_level=None, org_id=None, is_read=None):
    # 根据前端传递过来的参数，拼接成SQL查询用的条件
    filter_kwargs = self.make_filter_kwargs(
      date_from=date_from, date_to=date_to, user=user,
      asset=asset, system_user=system_user, input=input,
      session=session, risk_level=risk_level, org_id=org_id, is_read=is_read,
    )
    # 根据组织好的参数，去数据库中获取数据
    queryset = self.model.objects.filter(**filter_kwargs)
    return queryset

  def count(self, date_from=None, date_to=None,
            user=None, asset=None, system_user=None,
            input=None, session=None):
    filter_kwargs = self.make_filter_kwargs(
      date_from=date_from, date_to=date_to, user=user,
      asset=asset, system_user=system_user, input=input,
      session=session,
    )
    count = self.model.objects.filter(**filter_kwargs).count()
    return count
